package mobi.pooper;

import java.util.ArrayList;
import java.util.List;

import mobi.pooper.db.ICursor;
import mobi.pooper.db.IPicsDbAdapter;
import mobi.pooper.pictures.Picture;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray;

import static mobi.pooper.Rectangles.*;
import static mobi.pooper.Constants.*;

public class Assets {

	private static final String TAG = Assets.class.getSimpleName();

	private static final String FLYUP_FONT = Config.asString("Global.flyupFont", "ocr_a_small.fnt");
	private static final String SCORE_FONT = Config.asString("Global.scoreFont", "wellbutrin.fnt");
	private static final String TEXT_FONT = Config.asString("Global.textFont", "ocr_a.fnt");

	private static final float PLAYER_BORDER_WIDTH = Config.asFloat("Player.borderWidthPercent", 25.0f);
	private static final float PLAYER_BORDER_HEIGHT = Config.asFloat("Player.borderHeightPercent", 6.7f);
	private static final float PLAYER_FRAME_DURATION = Config.asFloat("Player.frameDuration", 0.2f);

	private static final float ROBOT_FRAME_DURATION = Config.asFloat("Robot.frameDuration", 0.1f);

	private static final float CAPTAIN_BORDER_WIDTH = Config.asFloat("Captain.borderWidthPercent", 16.7f);
	private static final float CAPTAIN_BORDER_HEIGHT = Config.asFloat("Captain.borderHeightPercent", 16.7f);
	private static final float CAPTAIN_FRAME_DURATION = Config.asFloat("Captain.frameDuration", 0.1f);

	private static final float PARTICLE_SIZE = Config.asFloat("particle.size", 0.1875f);

	private static TextureAtlas atlas;

	public static final float VIRTUAL_WIDTH = 30.0f;
	public static final float VIRTUAL_HEIGHT = 20.0f;

	public static Texture background1;

	public static Animation playerWalkingRightAnimation;
	public static Animation playerWalkingLeftAnimation;

	public static Animation robotWalkingLeftAnimation;
	public static Animation robotWalkingRightAnimation;
	public static Animation robotScanningAnimation;

	public static Animation nemesisAnimation;

	public static BitmapFont scoreFont;
	public static BitmapFont textFont;
	public static BitmapFont flyupFont;

	public static Sound[] chickenTaunts;
	public static Sound[] standardTaunts;
	public static Sound applause1;
	public static Sound negative;

	public static float playerWidth;
	public static float playerHeight;
	public static float robotWidth;
	public static float robotHeight;
	public static float captainWidth;
	public static float captainHeight;
	public static float playerShotWidth;
	public static float playerShotHeight;
	public static float robotShotWidth;
	public static float robotShotHeight;
	public static float particleWidth;
	public static float particleHeight;

	public static CollisionGeometry playerGeometry;
	public static CollisionGeometry captainGeometry;

	public static float pixelDensity;


	public static void checkTasksDb(){
		IPicsDbAdapter dba =((IPooperApplication)Gdx.app).getPicsDbAdapter();
		dba.open();
		
		FileHandle tasksDir = Gdx.files.internal(TASKS_PATH);
		FileHandle[] taskFiles = tasksDir.list("txt");
		
		Gdx.app.debug(TAG, "Found " + taskFiles.length + " tasks.");
		for(int i = 0; i < taskFiles.length; i++){
			FileHandle taskFile = taskFiles[i];
			Gdx.app.debug(TAG, "Task[" + i + "] = " + taskFile.nameWithoutExtension());
		}
		
		ICursor cursor = dba.getAllRecords();
		Gdx.app.debug(TAG, "Tasks db contains " + cursor.getCount() + " records.");		
		
		if(cursor.getCount() != taskFiles.length) fillTasksDb(dba, taskFiles);
		
		dba.close();
	}
	
	private static void fillTasksDb(IPicsDbAdapter dba, FileHandle[] taskFiles) {
		dba.deleteAllRecords();
		for(FileHandle taskFile : taskFiles){
			Picture task = new Picture(taskFile.nameWithoutExtension(), "description", 0, 0);
			dba.insertItem(task);
		}
	}

	public static void load () {
		pixelDensity = calculatePixelDensity();
		
		Gdx.app.debug(TAG, "Pixel density: " + pixelDensity);
		
		String textureDir = "data/textures/" + (int)pixelDensity;
		String textureFile = textureDir + "/pack";
//		atlas = new TextureAtlas(Gdx.files.internal(textureFile), Gdx.files.internal(textureDir));
		loadTextures();
//		loadFonts();
		loadSounds();
//		initialiseGeometries();
	}

	private static void loadTextures () {
		Texture.setEnforcePotImages(false);
        background1 = new Texture(Gdx.files.internal("data/images/bgr1.jpg"));
	}

	private static float calculatePixelDensity () {
		FileHandle textureDir = Gdx.files.internal("data/textures");
		FileHandle[] availableDensities = textureDir.list();
		FloatArray densities = new FloatArray();
		for (int i = 0; i < availableDensities.length; i++) {
			try {
				float density = Float.parseFloat(availableDensities[i].name());
				densities.add(density);
			}
			catch (NumberFormatException ex) {
				// Ignore anything non-numeric, such as ".svn" folders.
			}
		}
		densities.shrink();	// Remove empty slots to get rid of zeroes.
		densities.sort();	// Now the lowest density comes first.
		return CameraHelper.bestDensity(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, densities.items);
	}

	private static void loadFonts () {
		String fontDir = "data/fonts/" + (int)pixelDensity + "/";

		scoreFont = new BitmapFont(Gdx.files.internal(fontDir + SCORE_FONT), false);
		textFont = new BitmapFont(Gdx.files.internal(fontDir + TEXT_FONT), false);
		flyupFont = new BitmapFont(Gdx.files.internal(fontDir + FLYUP_FONT), false);

		scoreFont.setScale(1.0f / pixelDensity);
		textFont.setScale(1.0f / pixelDensity);
		flyupFont.setScale(1.0f / pixelDensity);
	}

	private static void loadSounds () {
//		standardTaunts = loadSounds("standard_taunts");
//		chickenTaunts = loadSounds("chicken_taunts");
		applause1 = loadSound("applause1.mp3");
		negative = loadSound("negative.mp3");
	}

	private static Sound[] loadSounds (String dir) {
		FileHandle dh = Gdx.files.internal("data/sounds/" + dir);
		FileHandle[] fhs = dh.list();
		List<Sound> sounds = new ArrayList<Sound>();
		for (int i = 0; i < fhs.length; i++) {
			String name = fhs[i].name();
			if (name.endsWith(".ogg")) {
				sounds.add(loadSound(dir + "/" + name));
			}
		}
		Sound[] result = new Sound[0];
		return sounds.toArray(result);
	}

	private static Sound loadSound (String filename) {
		return Gdx.audio.newSound(Gdx.files.internal("data/sounds/" + filename));
	}

	private static void initialiseGeometries () {

		// TODO: The below is a complete hack just to provide the player and captain with some collision geometry
		// so that he doesn't die when he's clearly not in contact with a wall, bullet or enemy. Ideally it would
		// be generated from the bitmap, or loaded.

		// Configure player collision geometry.
		Array<Rectangle> playerRectangles = new Array<Rectangle>();
		Rectangle r = new Rectangle();
		float x = (playerWidth * PLAYER_BORDER_WIDTH / 100.0f) / 2.0f;
		float y = (playerHeight * PLAYER_BORDER_HEIGHT / 100.0f) / 2.0f;
		float w = playerWidth - 2 * x;
		float h = playerHeight - 2 * y;
		setRectangle(r, x, y, w, h);
		playerRectangles.add(r);
		playerGeometry = new CollisionGeometry(playerRectangles);

		// Configure "captain" collision geometry.
		Array<Rectangle> captainRectangles = new Array<Rectangle>();
		r = new Rectangle();
		x = (captainWidth * CAPTAIN_BORDER_WIDTH / 100.0f) / 2.0f;
		y = (captainHeight * CAPTAIN_BORDER_HEIGHT / 100.0f) / 2.0f;
		w = captainWidth - 2 * x;
		h = captainHeight - 2 * y;
		setRectangle(r, x, y, w, h);
		captainRectangles.add(r);
		captainGeometry = new CollisionGeometry(captainRectangles);
	}

	private static float toWidth (TextureRegion region) {
		return region.getRegionWidth() / pixelDensity;
	}

	private static float toHeight (TextureRegion region) {
		return region.getRegionHeight() / pixelDensity;
	}

	public static void playSound (Sound sound) {
		sound.play(1);
	}

	public static void dispose() {
		background1.dispose();
	}
}
